/*
 *
 * Copyright (C) 2008 Ed Hong
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#ifndef SUBBANDBITS_H
#define SUBBANDBITS_H

#include "libQccPack.h"
#include <math.h>

#define MAXBITPLANES 32

typedef struct {
  int sign;
  unsigned int bits;
  int significance_level; // bitplane in which bit becomes significant.
  int descendant_minsiglevel; // min over (proper) descendants of siglevel. 
  unsigned char insignificance_level[MAXBITPLANES];
  int *locator;  // pointer to int index of location in heap
  int currbitplane; // which bitplane will be the next to be 
  // encoded/decoded? all bitplanes before currbitplane are valid. 
  // and known to decoder. 
} CoefficientData;

typedef struct {
  int num_rows;
  int num_cols;
  CoefficientData **coeff;
} SubbandBits;

typedef struct {
  SubbandBits *sub;
  int numSubbands;
  int numCoeffs;
} SubbandComponent;

typedef struct {
  int subband;
  int i; // row
  int j; // col
  int k;  // bitplane
  int comp; // component number
} sbploc;  // represents a location in an sbp. 

void printsbploc(const sbploc*l);

// r == row, c == col, s== subband.
int coeff_exists(const SubbandBits *sb, int r, int c);
int num_children(const SubbandComponent*sc, int r, int c, int s);

// compute sub/row/col of a given coeff's parent. 
// (note: parent may not exist at returned coordinate)
// passing in sub = 0 will yield psub=0, prow =-1, pcol=-1 
void computeParent(int s, int r, int c, int *psub, int *pr, int *pc) ;

// compute sub/row/col of a given coeff's primary child. (upper left-most child)
// (note: child may not exist at returned coordinate)
//  subband returned may also not exist. 
//  subband returned is -1 when input coeff does not have children and is at
//   subband 0. 
void computeChild(int s, int r, int c, int *childsub, int *childr, int *childc) ;

// bp == bitplane; use bp== -1 for sign bit. 
int bit_value(const SubbandBits *sb, int r, int c, int bp); // value of bit;
// for signs, return 1 for positive sign, 0 otherwise.

// if bit is not yet known in decoder, return -1; 
// else return same value as bit_value() call.  
int bit_value_causal(const SubbandBits *sb, int r, int c, int bp);

// modifies sc to store newbit. 
// returns 1 if newbit just caused the current coeff to become significant,
//  0 otherwise. Also automatically calls update_descendant_siglevels when
//  before returning 1. 
int set_bit_value(int newbit, SubbandComponent *sc, int subband, int r, int c, int bp);

// check all ancestors of input coefficient, seeing if
// it is necessary to update the descendant minsiglevels. 
void update_descendant_siglevels (SubbandComponent *sc, 
					 int subband, int r, int c);


void SubbandBitsFree(SubbandBits *sbits);
void SubbandBitsInitialize(SubbandBits *sbits); // initializes just fields
int SubbandBitsAlloc(SubbandBits *sb); // allocates coeff based on rows/cols field, also
// sets significance levels appropriately. 

// initializes and allocates arrays of subbandbits with allocated coeff arrays, based on subband_pyramid size
int SubbandComponentInitialize(SubbandComponent *output, const QccWAVSubbandPyramid *subband_pyramid);
void SubbandComponentFree(SubbandComponent *output);

void printSubbandComponent(const SubbandComponent *output);

// assumes maxmag is positive. returns power x such that
//  2^x is initial threshold. 
int computeInitialThreshold(const QccWAVSubbandPyramid * sbp, int numCompoments);

// currently also allocates coeff data. 
int ImageComponentConvertToBits(const QccIMGImageComponent *imgcmp, SubbandBits *sb, double firstthreshold, int debug);

void copySubbandComponentToSubbandPyramid(QccWAVSubbandPyramid *sbp, 
					  const SubbandComponent *sc, const sbploc * loc, 
					  int initialthreshpower) ;

// also allocates data for output_subbands. 
int CreateBits(const QccWAVSubbandPyramid *sbp, 
	       double firstthresh,	       
	       SubbandComponent *output_subbands, int debug);

// computes the number of levels of the wavelet transform should
// be applied to an image of size rows x cols. 
int computeNumWaveletLevels(int rows, int cols) ;


#endif /* SUBBANDBITS_H */
